// Adapted from article by Ed Swindelles

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Collections.Specialized;

namespace SmsMeta
{
    public enum HttpStatus
    {
        OK = 200,
        BadRequest = 400,
        MethodNotAllowed = 405,
        InternalError = 500,
        NotImplemented = 501,

    }

   public enum RestVerbs { GET, PUT, DELETE, POST, UNSUPPORTED };
   public enum OutputFormats { XML, JSON, TEXT };

   public abstract class IRestRequest
   {
      private RestVerbs verb = RestVerbs.UNSUPPORTED;
      private String method = null;
      private String[] arguments = null;
      private String contentType = "xml";
      private String data;
      private NameValueCollection query = null;

      abstract public Boolean IsValid
      {
         get;
      }
       /// <summary>
      /// The HTTP status code to return to the client after processing. 
      /// The default value is 200, indicating OK. 
       /// </summary>
      public Int32 StatusCode = (Int32)HttpStatus.OK;

       /// <summary> HTTP verb, with support for GET, POST, PUT and DELETE</summary>
      public RestVerbs Verb
      {
         get { return this.verb; }
      }
       /// <summary>
      /// The method being called (see web config httpHandler the add instruction for used class)
       /// </summary>
      public String Method
      {
         get { return this.method; }
      }

       /// <summary> All of the URL arguments specified after the Method.</summary>
      public String[] Arguments
      {
         get { return this.arguments; }
      }

       /// <summary> The expected return content type in HTTP header format </summary>
      public String ContentType
      {
         get
         {
            return (this.contentType == "xml") ? "text/xml" :
               ((this.contentType == "json") ? "application/json" : "text/plain");
         }
      }

       /// <summary> The abbreviated version of ContentType </summary>
      public OutputFormats OutputFormat
      {
         get
         {
            return (this.contentType == "xml") ? OutputFormats.XML :
               ((this.contentType == "json") ? OutputFormats.JSON : OutputFormats.TEXT);
         }
      }

       /// <summary>The raw data sent to the web service from the client </summary>
      public String Data
      {
         get { return this.data; }
      }

       /// <summary>  A collection of query string arguments, if present. </summary>
      public NameValueCollection Query
      {
         get 
         {
             return this.query; 
         }
      }

      public IRestRequest(System.Web.HttpRequest r)
      {
         String v = r.HttpMethod.ToUpper();
         this.verb = (v == "GET") ? RestVerbs.GET : (
                     (v == "PUT") ? RestVerbs.PUT : (
                     (v == "POST") ? RestVerbs.POST : (
                     (v == "DELETE") ? RestVerbs.DELETE : RestVerbs.UNSUPPORTED)));

         IEnumerable<String> args = (from s in r.Url.Segments select s.Replace("/", "").ToLower()).Skip(1);
         this.method = args.First();
         this.arguments = args.Skip(1).ToArray();

         String f = r.QueryString["format"];
         if ((new[] { "xml", "json", "text" }).Contains(f))
         {
            this.contentType = f;
         }

         if (r.InputStream != null)
         {
            System.IO.Stream s = r.InputStream;
            s.Seek(0, System.IO.SeekOrigin.Begin);
            Int32 len = Convert.ToInt32(s.Length);
            Byte[] arr = new Byte[len];
            s.Read(arr, 0, len);

            if (arr.Length > 0)
            {
               this.data = (new ASCIIEncoding()).GetString(arr);
            }
         }

         this.query = r.QueryString;
      }
   }
}